import { newArrayProto } from "./array"
import Dep from "./dep"

export function observe(data) {
    // 对这个对象进行劫持
    if(typeof data !== 'object' || data === null) return

    // 如果一个对象被劫持过就不用再劫持了
    // 要判断一个对象是否被劫持过，可以增添一个实例来判断是否被劫持过
    if(data.__ob__ instanceof Observer) {
        return data.__ob__
    }
    
    return new Observer(data)

}

export function defineReactive(target, key, value) { // 闭包  属性劫持
    observe(value)  // 如果值是对象，会再做一次劫持

    let dep = new Dep()
    Object.defineProperty(target, key, {
        get() {
            if(Dep.target) {
                dep.depend() // 让这个属性的dep记住当前的watcher
            }
            return value
        },
        set(newVal) {
            if(value === newVal) return;
            // 设置的值是一个对象的话应该再次代理
            observe(newVal)
            value = newVal
            dep.notify()
        }
    })
}
class Observer {
    constructor(data) {

        Object.defineProperty(data, '__ob__', {
            value: this,
            enumerable: false  // 不可枚举。循环的时候无法获取
        })
        // data.__ob__ = this  // 给数据加了一个标识，如果数据上有__ob__,则被观测过
        if(Array.isArray(data)) {
            // 这里重写数组的7个变异方法
            data.__proto__ = newArrayProto
            this.observeArray(data)
        } else {
            this.walk(data)
        }
    }
    walk(data) {
        // 让data循环对象，对属性依次劫持
        // 重新定义属性
        Object.keys(data).forEach(key => defineReactive(data, key, data[key]))
    }
    observeArray(data) {
        data.forEach(item => observe(item))
    }
} 